/***************************************************************************
 *   Copyright (C) 2010 by Oleg Goncharov  *
 *   $EMAIL$                           *                          
 *                                                                         *
 *   This file is part of ChessVision.                                     *
 *                                                                         *
 *   ChessVision is free software; you can redistribute it and/or modify   *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <opencv/cv.h>

#include "cpointbackhist.h"

CPointBackHist::CPointBackHist(IplImage * sample, float min_size_mul, float max_size_mul, int _nsteps) {
	size = cvGetSize(sample);
	nsteps = _nsteps;
	min_mul = min_size_mul;
	mul_step = (max_size_mul - min_size_mul) / nsteps;
	
	method = CV_COMP_CORREL;
	therehold = 0.0;
	
	int hsize[] = {30, 32};
	float h_range[] = {1, 180}, s_range[] = {0, 255};
	float * ranges[] = { h_range, s_range };
	
	IplImage* h_plane = cvCreateImage( size, 8, 1 );
	IplImage* s_plane = cvCreateImage( size, 8, 1 );
	IplImage* v_plane = cvCreateImage( size, 8, 1 );
	IplImage* planes[] = { h_plane, s_plane };
	IplImage* hsv = cvCreateImage( size, 8, 3 );
	
	cvCvtColor(sample, hsv, CV_BGR2HSV);
	cvSplit( hsv, h_plane, s_plane, v_plane, 0 );
	hist = cvCreateHist( 2, hsize, CV_HIST_ARRAY, ranges, 1);
	cvCalcHist( planes, hist, 0, 0 );
	cvNormalizeHist(hist, 1.0);
	
	cvReleaseImage(&h_plane);
	cvReleaseImage(&s_plane);
	cvReleaseImage(&v_plane);
	cvReleaseImage(&hsv);
}

CPointBackHist::~CPointBackHist() {
	cvReleaseHist(& hist);
}


bool CPointBackHist::DetectPoint(const IplImage* img, cv::Point2f& point) {
	IplImage * diff = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1);
	CvPoint min_loc;
	double min, max, best = 1e100; 
	double mul = min_mul;
	
	IplImage* h_plane = cvCreateImage( cvGetSize(img), 8, 1 );
	IplImage* s_plane = cvCreateImage( cvGetSize(img), 8, 1 );
	IplImage* v_plane = cvCreateImage( cvGetSize(img), 8, 1 );
	IplImage* planes[] = { h_plane, s_plane };
	IplImage* hsv = cvCreateImage( cvGetSize(img), 8, 3 );
	CvSize cur_size;
	
	cvCvtColor(img, hsv, CV_BGR2HSV);
	cvSplit( hsv, h_plane, s_plane, v_plane, 0 );
	
	cvReleaseImage(&hsv);
	
	for(int i = 0; i < nsteps; i++, mul += mul_step) {
		cur_size = cvSize(cvRound(size.width*mul), cvRound(size.height*mul));
		cvSetImageROI(diff, cvRect(0,0, img->width - cur_size.width + 1, img->height - cur_size.height + 1));
		cvCalcBackProjectPatch(&planes, diff, cur_size, hist, method, 1.0);
	
		cvMinMaxLoc(diff, &min, &max, &min_loc, 0);
		if (min < best) {
			best = min;
			point.x = min_loc.x + cur_size.width/2; point.y = min_loc.y + cur_size.height/2;
		}
	}
	
	cvReleaseImage(&h_plane);
	cvReleaseImage(&s_plane);
	cvReleaseImage(&v_plane);
	cvReleaseImage(&diff);
	if (min > therehold) return false;
	else return true;
}

